/**
 * 
 */
package com.toncen.samepms.interceptor;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.toncen.samepms.common.AbstractAction;
import com.toncen.samepms.common.ComitConstant;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.util.AnnotationUtils;

/**
 * 
 * Session范围拦截器：将Action中指定标记的属性取出、存入Session中
 * 
 * @author tch
 * 
 */
public class SessionScopeInterceptor extends MethodFilterInterceptor {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4759165676819171063L;

	protected Log logger = LogFactory.getLog(this.getClass());

	/**
	 * 
	 */
	public SessionScopeInterceptor() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.opensymphony.xwork2.interceptor.MethodFilterInterceptor#doIntercept(com.opensymphony.xwork2.ActionInvocation)
	 */
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		if (invocation.getAction() instanceof AbstractAction) {// 是数据库操作的Action
			String result = "";
			AbstractAction action = (AbstractAction) invocation.getAction();
			Method method = action.getClass().getMethod(invocation.getProxy().getMethod());
			processBegin(invocation, method);//
			processIns(invocation);//
			result = invocation.invoke();
			processOuts(invocation);//
			if (!action.hasErrors()) {
				processEnd(invocation, method);//
			}
			return result;
		} else {
			return invocation.invoke();
		}
	}

	/**
	 * 申请Session空间
	 * 
	 * @param invocation
	 * @param method
	 */
	private void processBegin(ActionInvocation invocation, Method method) {
		Begin begin = method.getAnnotation(Begin.class);
		if (begin != null) {
			outInfo(invocation.getAction(), "执行【Begin】...");
			invocation.getInvocationContext().getSession().put(getSessionAttributeName(invocation), new HashMap<String, Object>());
		}
	}

	/**
	 * 从Session空间取出注入action属性中
	 * 
	 * @param invocation
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private void processIns(ActionInvocation invocation) throws Exception {
		List<Field> annotatedFields = new ArrayList<Field>();
		AnnotationUtils.addAllFields(In.class, invocation.getAction().getClass(), annotatedFields);
		if (annotatedFields.size() > 0) {
			outInfo(invocation.getAction(), "执行【In Action】...");
			Object obj;
			Map<String, Object> sessions = (HashMap<String, Object>) invocation.getInvocationContext().getSession().get(getSessionAttributeName(invocation));
			if (sessions != null) {
				for (Field f : annotatedFields) {
					obj = sessions.get(f.getName());
					if (obj != null) {
						PropertyUtils.setProperty(invocation.getAction(), f.getName(), obj);
						outInfo(invocation.getAction(), "In【" + f.getName() + "】=【" + obj + "】/【"+PropertyUtils.getProperty(invocation.getAction(), f.getName())+"】...");
					}
				}
			}
			outInfo(invocation.getAction(), "In【" + getSessionAttributeName(invocation) + "】:【" + sessions + "】...");
		}
	}

	/**
	 * 从action属性取出存入Session空间中
	 * 
	 * @param invocation
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private void processOuts(ActionInvocation invocation) throws Exception {
		List<Field> annotatedFields = new ArrayList<Field>();
		AnnotationUtils.addAllFields(Out.class, invocation.getAction().getClass(), annotatedFields);
		if (annotatedFields.size() > 0) {
			outInfo(invocation.getAction(), "执行【Out Session】...");
			Map<String, Object> sessions = (HashMap<String, Object>) invocation.getInvocationContext().getSession().get(getSessionAttributeName(invocation));
			if (sessions != null) {
				for (Field f : annotatedFields) {
					Object obj = PropertyUtils.getProperty(invocation.getAction(), f.getName());
					if (obj != null) {
						outInfo(invocation.getAction(), "Out【" + f.getName() + "】=【" + obj + "】/【"+sessions.get(f.getName())+"】...");
						sessions.put(f.getName(), obj);
					}
				}
			}
			outInfo(invocation.getAction(), "Out【" + getSessionAttributeName(invocation) + "】:【" + sessions + "】...");
		}
	}

	/**
	 * 释放Session空间
	 * 
	 * @param invocation
	 * @param method
	 */
	private void processEnd(ActionInvocation invocation, Method method) {
		End end = method.getAnnotation(End.class);
		if (end != null) {
			outInfo(invocation.getAction(), "执行【End】...");
			invocation.getInvocationContext().getSession().remove(getSessionAttributeName(invocation));
		}
	}

	/**
	 * 获取Session空间中属性名称
	 * 
	 * @param invocation
	 * @return
	 */
	private String getSessionAttributeName(ActionInvocation invocation) {
		return getSessionAttributeName(invocation.getAction().getClass().getName());

	}

	/**
	 * 获取Session空间中属性名称
	 * 
	 * @param actionClassName
	 * @return
	 */
	public static String getSessionAttributeName(String actionClassName) {
		return "Action" + "#" + actionClassName;
	}

	/**
	 * @param targetObj
	 * @param content
	 */
	private void outInfo(Object targetObj, Object content) {
		if (ComitConstant.isDeveloperMode()) {
			System.out.println("[" + targetObj.getClass().getSimpleName() + "]:" + content);
		}
	}
}
